
Type CalSkeleton

	Field m_coreSkeleton:CalCoreSkeleton
	Field m_vectorBone:CalBone[]
	Field m_isBoundingBoxesComputed:Byte
	
	
	Method New()
		m_coreSkeleton = Null
		m_vectorBone = New CalBone[0]
		m_isBoundingBoxesComputed = False
	End Method
	
	Function FromCore:CalSkeleton(coreSkeleton:CalCoreSkeleton)
		Local skel:CalSkeleton = New CalSkeleton
		skel.m_coreSkeleton = coreSkeleton
		skel.m_vectorBone = New CalBone[0]
		skel.m_isBoundingBoxesComputed = False		
	
		Local vectorCoreBone:CalCoreBone[] = coreSkeleton.getVectorCoreBone()
		
		Local boneCount:Int = vectorCoreBone.length

		For Local boneId:Int = 0 To boneCount-1
			Local bone:CalBone = CalBone.FromCore(vectorCoreBone[boneId])
	
			' set skeleton in the bone instance
			bone.setSkeleton(skel)
	
			' insert bone into bone vector
			skel.m_vectorBone = skel.m_vectorBone[..skel.m_vectorBone.length+1]
			skel.m_vectorBone[skel.m_vectorBone.length-1] = bone
		Next
		Return skel
	End Function
	
	
	Method calculateState()
		' calculate all bone states of the skeleton
		Local listRootCoreBoneId:Int[] = m_coreSkeleton.getVectorRootCoreBoneId()
	
		For Local iRootCoreBoneId:Int = 0 To listRootCoreBoneId.length-1
			m_vectorBone[ listRootCoreBoneId[iRootCoreBoneId] ].calculateState()
		Next
		m_isBoundingBoxesComputed = False		
	End Method
	
	Method clearState()
		' clear all bone states of the skeleton
		For Local boneId:Int = 0 To m_vectorBone.length-1
			m_vectorBone[boneId].clearState()
		Next
		m_isBoundingBoxesComputed = False		
	End Method
	
	Method Create(coreSkeleton:CalCoreSkeleton)
		DebugLog "Not Implemented Yet..."
	End Method
	
	Method getBone:CalBone(boneId:Int)
		Return m_vectorBone[boneId]
	End Method
	
	Method getCoreSkeleton:CalCoreSkeleton()
		Return m_coreSkeleton
	End Method
	
	Method getVectorBone:CalBone[]()
		Return m_vectorBone
	End Method
	
	Method getBoneCount:Int()
		Return m_vectorBone.length
	End Method
	
	Method lockState()
		' lock all bone states of the skeleton
		For Local boneId:Int = 0 To m_vectorBone.length-1
			m_vectorBone[boneId].lockState()
		Next		
	End Method
	
	Method getBoneBoundingBox:CalMinMax(Mini:CalVector=Null, Maxi:CalVector=Null)
	
		If Mini = Null Then
			Mini = New CalVector
		EndIf
		If Maxi = Null Then
			Maxi = New CalVector
		EndIf
	
		If m_isBoundingBoxesComputed = False Then
			calculateBoundingBoxes()
		EndIf
	
		Local boneId:Int = 0
		If m_vectorBone.length > 0 Then
			Local translation:CalVector = m_vectorBone[boneId].getTranslationAbsolute()
	
			Mini.assignvector(translation)
			Maxi.assignvector(translation)
	
			boneId = boneId + 1
		EndIf
	
		For boneId = boneId To m_vectorBone.length-1
			translation = m_vectorBone[boneId].getTranslationAbsolute()
	
			If translation.x > Maxi.x Then
				Maxi.x = translation.x
			ElseIf translation.x < Mini.x Then
				Mini.x = translation.x
			EndIf
			
			If translation.y > Maxi.y Then
				Maxi.y = translation.y
			ElseIf translation.y < Mini.y Then
				Mini.y = translation.y
			EndIf
			If translation.z > Maxi.z Then
				Maxi.z = translation.z
			ElseIf translation.z < Mini.z Then
				Mini.z = translation.z
			EndIf
		Next
		Local mnmx:CalMinMax = New CalMinMax
		mnmx.Minimum = Mini
		mnmx.Maximum = Maxi
		Return 	mnmx
	
	End Method
	
	Method calculateBoundingBoxes()
		If m_isBoundingBoxesComputed = True Then 
			Return
		EndIf
		
		For Local boneId:Int = 0 To m_vectorBone.length-1 
			m_vectorBone[boneId].calculateBoundingBox()
		Next
		m_isBoundingBoxesComputed = True		
	End Method
	
	Method getBonePoints:Int(pointBuffer:Float[])
		Local boneCount:Int = m_vectorBone.length
	
		Local p:Int = 0
		For Local boneId:Int = 0 To boneCount-1
			Local translation:CalVector = m_vectorBone[boneId].getTranslationAbsolute()
	
			pointBuffer[p    ] = translation.x
			pointBuffer[p + 1] = translation.y
			pointBuffer[p + 2] = translation.z
	
			p = p+3
		Next
	
		Return boneCount		
		
	End Method

	Method getBonePointsStatic:Int(pointBuffer:Float[])
		Local boneCount:Int = m_vectorBone.length
	
		Local p:Int = 0
		For Local boneId:Int = 0 To boneCount-1
			Local translation:CalVector = m_vectorBone[boneId].getCoreBone().getTranslationAbsolute()
	
			pointBuffer[p    ] = translation.x
			pointBuffer[p + 1] = translation.y
			pointBuffer[p + 2] = translation.z
	
			p = p+3
		Next
	
		Return boneCount		
		
	End Method
	
	Method getBoneLines:Int(lineBuffer:Float[])
	
		Local boneCount:Int = m_vectorBone.length
		
		Local p:Int = 0
		Local numLines:Int = 0
		For Local boneId:Int = 0 To boneCount-1
			Local bone:CalBone = m_vectorBone[boneId]
	
			Local parentId:Int = bone.getCoreBone().getParentId()
			If parentId <> -1 Then
				Local parent:CalBone = m_vectorBone[parentId]
	
				Local translation:CalVector = bone.getTranslationAbsolute()
				Local translationParent:CalVector = parent.getTranslationAbsolute()
	
				lineBuffer[p    ] = translationParent.x
				lineBuffer[p + 1] = translationParent.y
				lineBuffer[p + 2] = translationParent.z
	
				lineBuffer[p + 3] = translation.x
				lineBuffer[p + 4] = translation.y
				lineBuffer[p + 5] = translation.z
	
				p = p + 6
				numLines = numLines + 1
			EndIf
		Next
	
		Return numLines		
	End Method


	Method getBoneLinesStatic:Int(lineBuffer:Float[])
	
		Local boneCount:Int = m_vectorBone.length
		
		Local p:Int = 0
		Local numLines:Int = 0
		For Local boneId:Int = 0 To boneCount-1
			Local bone:CalBone = m_vectorBone[boneId]
	
			Local parentId:Int = bone.getCoreBone().getParentId()
			If parentId <> -1 Then
				Local parent:CalBone = m_vectorBone[parentId]
	
				Local translation:CalVector = bone.getCoreBone().getTranslationAbsolute()
				Local translationParent:CalVector = parent.getCoreBone().getTranslationAbsolute()
	
				lineBuffer[p    ] = translationParent.x
				lineBuffer[p + 1] = translationParent.y
				lineBuffer[p + 2] = translationParent.z
	
				lineBuffer[p + 3] = translation.x
				lineBuffer[p + 4] = translation.y
				lineBuffer[p + 5] = translation.z
	
				p = p + 6
				numLines = numLines + 1
			EndIf
		Next
	
		Return numLines		
	End Method

End Type

Type CalMinMax

	Field Minimum:CalVector
	Field Maximum:CalVector

	

End Type
